package com.fedming.bottomnavigationdemo.Call;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Build;
import android.os.Handler;
import android.support.annotation.RequiresApi;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import com.aill.androidserialport.ByteUtil;
import com.aill.androidserialport.SerialPort;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fedming.bottomnavigationdemo.HomeActivity;
import com.fedming.bottomnavigationdemo.R;
import com.fedming.bottomnavigationdemo.Util.CameraUtils;
import com.fedming.bottomnavigationdemo.Util.TimeUtil;

import java.io.OutputStream;
import java.math.BigInteger;
import java.net.URI;
import java.util.Date;

public class my_SignalClient {

    private static final String TAG = "my_SignalClient";
    public static String toUserId = "";
    public static String userId = "1000";
    public static boolean isVideoCall = false;
    public String websocketUrl = "";
    public Context mcontext;
    private static my_SignalClient mInstance;
    public static boolean initiator = false;
    private OnSignalEventListener mOnSignalEventListener;
    //private SerialManager serialManager = new SerialManager();

    private JWebSocketClient mSocket;

    static boolean wm8960MusicStop = false; //设置当前是否播放打电话的音乐
    public static boolean Waiting=false; //标志当前是否在等待接听或被接听，以此来决定是否播放音效


    public interface OnSignalEventListener {
        void onConnected();
        void onConnecting();
        void onDisconnected();
        void onUserJoined(String roomName, String userID);
        void onUserLeaved(String roomName, String userID);
        void onRemoteUserJoined(String roomName);
        void onRemoteUserLeaved(String roomName, String userID);
        void onRoomFull(String roomName, String userID);
        void onMessage(JSONObject message);
        void start_call();
    }



    public static my_SignalClient getInstance() {
        synchronized (my_SignalClient.class) {
            if (mInstance == null) {
                mInstance = new my_SignalClient();
            }
        }
        return mInstance;
    }

    public void setSignalEventListener(final OnSignalEventListener listener) {
        mOnSignalEventListener = listener;
    }



    public boolean websocketIsalive(){
        if(mSocket!=null){
            if(mSocket.isClosed()){
                return false;
            }
            return true;
        }

        return false;
    }


    public Handler getmHandler() {
        return mHandler;
    }

    public static long getHeartBeatRate() {
        return HEART_BEAT_RATE;
    }

    public Runnable getHeartBeatRunnable() {
        return heartBeatRunnable;
    }

    private static final long HEART_BEAT_RATE = 10 * 1000;//每隔10秒进行一次对长连接的心跳检测
    private Handler mHandler = new Handler();

    private Runnable heartBeatRunnable = new Runnable() {
        @Override
        public void run() {
            if (mSocket != null) {
                if (mSocket.isClosed()) {
                    reconnectWebsocket();
                }
            } else {
                //如果client已为空，重新初始化websocket,第一次初始化的时候已经得到了websocketUrl,userId,mcontext这三个参数
                startWebsocket(websocketUrl,userId,mcontext);
            }
            //定时对长连接进行心跳检测
            mHandler.postDelayed(this, HEART_BEAT_RATE); //10秒后调用heartBeatRunnable对象，相当于重新设置了一个10秒的定时器
        }
    };

    /**
     * 开启重连websocket
     */

    private void reconnectWebsocket() {
        mHandler.removeCallbacks(heartBeatRunnable);//移除定时器
        new Thread() {
            @Override
            public void run() {
                try {
                    //重连
                    mSocket.reconnectBlocking();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Log.e(TAG,e.toString());
                    Log.e("websocket","websocket重新连接失败");
                }
            }
        }.start();
    }


    public void startWebsocket(String url, String userid, Context context) {
        if(websocketIsalive()){
            return;
        }
        userId = userid;
        System.out.println("websocket"+url);
        websocketUrl = url;
        mcontext = context;
        System.out.println("uri:"+url+userId);
        URI uri = URI.create( url + userId);
        mSocket = new JWebSocketClient(uri) {
            @Override
            public void onMessage(String message) {
                //message就是接收到的消息
                Log.e("JWebSClientService收到消息：", message);

                JSONObject data = JSON.parseObject(message);
                HomeActivity.t2 = ""+ new Date().getTime()/1000*1000;
                toUserId = data.getJSONObject("message").getString("userId");

                switch (data.getString("type")) {
                    case "ask":  //护士站端请求连接，表示被动接听
                        my_SignalClient.getInstance().initiator = false; //标志我方为被动拨打的
                        HomeActivity.physicalLight("灭灯");
                        ((Activity)context).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(mcontext,"护士站来电",Toast.LENGTH_LONG).show();
                                if ( CameraUtils.hasCamera(mcontext) && CameraUtils.isCameraCanUse()){
                                    my_SignalClient.getInstance().isVideoCall = true;

                                }
                                else{
                                    my_SignalClient.getInstance().isVideoCall = false;
                                }


                                //先播放一段提示音，播放完毕后就开始通话
                                calledInRing();

                                Log.e(TAG,"向远端发送tell请求");
                                JSONObject tosend = new JSONObject();
                                tosend.put("type","tell");
                                JSONObject inner_message = new JSONObject();
                                inner_message.put("userId",my_SignalClient.getInstance().userId);
                                inner_message.put("toUserId",my_SignalClient.getInstance().toUserId);
                                inner_message.put("video",my_SignalClient.getInstance().isVideoCall);
                                tosend.put("message",inner_message);
                                my_SignalClient.getInstance().sendMessage(tosend);

                            }
                        });
                        break;
//                    case "offline":
//                        my_SignalClient.getInstance().callingOutMusicStop(); //关闭等待音乐
//                        mOnSignalEventListener.onMessage(JSON.parseObject(message));
//                        ((Activity)context).runOnUiThread(new Runnable() {
//                            @Override
//                            public void run() {
//                                Toast.makeText(mcontext,"护士站不在线",Toast.LENGTH_LONG).show();
//                            }
//                        });
//                        break;

                    case "connect":

                        if(my_SignalClient.getInstance().isVideoCall){
                            Intent intent = new Intent(mcontext, VideoCallActivity.class);
                            mcontext.startActivity(intent);
                        }
                        else{
                            Intent intent = new Intent(mcontext, AudioCallActivity.class);
                            mcontext.startActivity(intent);
                        }
                        break;
                    case "start": //收到“start"表示对方已经同意音视频连接了
                        my_SignalClient.getInstance().Waiting = false; //标志此时已经不在等待对方接听了,因为对方已经接听了
                        HomeActivity.physicalLight("灭灯");
                        my_SignalClient.getInstance().callingOutMusicStop(); //关闭等待音乐
//                        new Thread(new Runnable() {
//                            @Override
//                            public void run() {
//                                try {
//                                    Thread.sleep(5000);
//                                } catch (InterruptedException e) {
//                                    e.printStackTrace();
//                                }
//                                my_SignalClient.getInstance().callingOutMusicStop(); //关闭等待音乐
//                            }
//                        }).start();

                        //开始createoffer
                        mOnSignalEventListener.start_call();
                        break;
                    case "offer":

                        mOnSignalEventListener.onMessage(JSON.parseObject(message));
                        break;
                    case "answer":
                        mOnSignalEventListener.onMessage(JSON.parseObject(message));
                        break;
                    case "icecandidate":

                        mOnSignalEventListener.onMessage(JSON.parseObject(message));
                        break;
                    case "hangup":
                        HomeActivity.t2 = "";
                        mOnSignalEventListener.onMessage(JSON.parseObject(message));
                        break;
                    case "refuse":
                        //远端拒绝接听
                        my_SignalClient.getInstance().callingOutMusicStop(); //关闭等待音乐
                        if(TimeUtil.DayNight()==1)
                            HomeActivity.physicalLight("亮灯");
                        else
                            HomeActivity.physicalLight("灭灯");
                        mOnSignalEventListener.onMessage(JSON.parseObject(message));
                        break;



                }
            }

            //这个websocket用来监听服务器发来的消息
        };
        try {
            mSocket.connectBlocking();
        } catch (InterruptedException e) {
            Log.e("websocket","websocket连接失败");
            e.printStackTrace();
        }

    }

    public void closeSocket() {

        Log.i(TAG, "关闭视频通话");

        try {
            if (null != mSocket) {
                mSocket.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "关闭websocket发生错误");
        } finally {
            mSocket = null;
        }
    }




    public void sendMessage(JSONObject message) {
        Log.i(TAG, "向信令服务器发送消息: " + message);
        if (mSocket == null) {
            return;
        }
        mSocket.send(message.toString()); //发送消息给服务器
    }
    //打电话时播放声音
    public void callingOutMusicPlay()
    {
        wm8960MusicStop = false;
        class MyRunnable implements Runnable {

            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void run() {
                int STREAM_DAUDIO0 =11;
                int MODE_EXT0_STREAM = 2;
                int bufferSize = AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
                AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);
                //AudioTrack audioTrack = new AudioTrack(STREAM_DAUDIO0, 48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM,AudioManager.AUDIO_SESSION_ID_GENERATE,MODE_EXT0_STREAM);

                FileInputStream fis = null;
                InputStream in=null;

                try {
                    audioTrack.play();

                    in = mcontext.getResources().openRawResource(R.raw.yin);

                    byte[] buffer = new byte[bufferSize];

                    int len = 0;

                    while( !wm8960MusicStop)
                    {
                        len = in.read(buffer);
                        if(len==-1) {
                            break;
                        } //是不是只播放一次呢？？？
                        Log.d(TAG, "playPCMRecord: len " + len);

                        audioTrack.write(buffer, 0, len);
                    }
                    Thread.currentThread().sleep(1000);

                } catch (Exception e) {
                    e.printStackTrace();
                    Log.e(TAG, "playPCMRecord: e : " + e);
                }
                finally {

                    if (audioTrack != null) {

                        audioTrack.stop();
                        audioTrack.release();
                        audioTrack = null;
                    }
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if(in!=null) {
                        try {
                            in.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

        MyRunnable playPCMRecord = new MyRunnable();

        Thread thread1 = new Thread(playPCMRecord, "audioTrack");

        thread1.start();
        setWiredHead(mcontext);
    }
    public void callingOutMusicStop(){
        wm8960MusicStop =true;
    }
    public void calledInRing(){ //注意播放这个声音没有开线程，默认这个函数要在主线程里调用
        int STREAM_DAUDIO0 =11;
        int MODE_EXT0_STREAM = 2;
        int bufferSize = AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
        AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);
        //AudioTrack audioTrack = new AudioTrack(STREAM_DAUDIO0, 48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM,AudioManager.AUDIO_SESSION_ID_GENERATE,MODE_EXT0_STREAM);
        FileInputStream fis = null;
        InputStream in=null;
        try {
            audioTrack.play();

            in = mcontext.getResources().openRawResource(R.raw.ring);

            byte[] buffer = new byte[bufferSize];

            int len = 0;

            while(true)
            {
                len = in.read(buffer);
                if(len==-1) break; //只播放一次
                Log.d(TAG, "playPCMRecord: len " + len);

                audioTrack.write(buffer, 0, len);
            }
            Thread.currentThread().sleep(1000);

        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "playPCMRecord: e : " + e);
        }
        finally {

            if (audioTrack != null) {

                audioTrack.stop();
                audioTrack.release();
                audioTrack = null;
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(in!=null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
    public void callEndRing(){
        class MyRunnable implements Runnable {

            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void run() {
                int STREAM_DAUDIO0 =11;
                int MODE_EXT0_STREAM = 2;
                //这个采样率设置会影响声音的质量的
                int bufferSize = AudioTrack.getMinBufferSize(5000 , AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
                AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 5000 , AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);
                //AudioTrack audioTrack = new AudioTrack(STREAM_DAUDIO0, 48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM,AudioManager.AUDIO_SESSION_ID_GENERATE,MODE_EXT0_STREAM);

                FileInputStream fis = null;
                InputStream in=null;

                try {
                    audioTrack.play();

                    in = mcontext.getResources().openRawResource(R.raw.end_ring);

                    byte[] buffer = new byte[bufferSize];

                    int len = 0;

                    while(true)
                    {
                        len = in.read(buffer);
                        if(len==-1) break; //是不是只播放一次呢？？？
                        Log.d(TAG, "playPCMRecord: len " + len);

                        audioTrack.write(buffer, 0, len);
                    }
                    Thread.currentThread().sleep(1000);

                } catch (Exception e) {
                    e.printStackTrace();
                    Log.e(TAG, "playPCMRecord: e : " + e);
                }
                finally {

                    if (audioTrack != null) {

                        audioTrack.stop();
                        audioTrack.release();
                        audioTrack = null;
                    }
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if(in!=null) {
                        try {
                            in.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

        MyRunnable playPCMRecord = new MyRunnable();

        Thread thread1 = new Thread(playPCMRecord, "hh");

        thread1.start();

    }

    public static void setWiredHead(Context context) {
        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        audioManager.startBluetoothSco();
        audioManager.setBluetoothScoOn(true);
        audioManager.setSpeakerphoneOn(false);
    }
}
